﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ComputerArchitecture.Core;
using ComputerArchitecture.Core.Logging;
using ComputerArchitecture.Numbers;
using ComputerArchitecture.Units.Integers.Unsigned.Interfaces;

namespace ComputerArchitecture.Units.Integers.Unsigned.Implementations
{
    public class UnsignedAdderUnit : LoggingObject, IUnsignedAdderUnit
    {
        #region Constuctors

        #endregion

        public UnsignedAdderUnit(ILoggingService loggingService) 
            : base(loggingService)
        {
        }

        IBitNumber IAdderUnit.Add(IBitNumber first, IBitNumber second, out bool overflow)
        {
            return this.Add((IUnsignedBitNumber) first, (IUnsignedBitNumber) second, out overflow);
        }

        public IUnsignedBitNumber Add(IUnsignedBitNumber first, IUnsignedBitNumber second, out bool overflow)
        {
            ArgumentValidator.NullValidate(first, "first");
            ArgumentValidator.NullValidate(second, "second");
            if (first.Size != second.Size)
            {
                throw new IncompatibleSizeException();
            }
            IUnsignedBitNumber result = new UnsignedBitNumber(first.Size);
            Bit carryBit = Bit.Zero;
            for (int i = first.Size - 1; i >= 0; --i)
            {
                result[i] = FullAdder.Add(first[i], second[i], carryBit, out carryBit);
            }
            overflow = carryBit.IsSet;
            return result;
        }

        public IUnsignedBitNumber Inc(IUnsignedBitNumber value, out bool overflow)
        {
            ArgumentValidator.NullValidate(value, "first");
            IUnsignedBitNumber result = new UnsignedBitNumber(value.Size);
            Bit carryBit = Bit.One, zeroBit = Bit.Zero;
            for (int i = value.Size - 1; i >= 0; --i)
            {
                result[i] = FullAdder.Add(value[i], zeroBit, carryBit, out carryBit);
            }
            overflow = carryBit.IsSet;
            return result;
        }
    }
}
